#pragma once

#include <stdint.h>
#include <type_traits>
#include <concepts>
#include <functional>

#include "Misc/CommonMacros.h"


namespace WH
{
	//hashable with std library
	template <class T>
	concept HashableWithSTD = requires(const T& Value)
	{ 
		{ std::hash<T>{}(Value) } ->std::same_as<uint64_t>;
	};
	template <typename T>
	requires HashableWithSTD<T>
	uint64_t GetHashCode(const T& InValue)
	{
		return std::hash<T>{}(InValue);
	}

	template <typename T>
	uint64_t GetHashCode(const T*& InValue)
	{
		return (uint64_t)InValue;
	}

	//hashable with a member GetHashCode function  in type
	//function type : uint64_t GetHashCode(const T&);
	template <class T>
	concept HashableWithMemberFunction = requires(const T & Value)
	{
		{ Value.GetHashCode()} ->std::same_as<uint64_t>;
	};


	template <typename T>
	requires HashableWithMemberFunction<T>
	uint64_t GetHashCode(const T& InValue)
	{
		return InValue.GetHashCode();
	}

	template <class T>
	concept Hashable = requires(const T & Value)
	{
		{ GetHashCode(Value) } ->std::same_as<uint64_t>;
	};


	uint64_t WHENGINE_API  HashCombine(size_t A, size_t B);

}